home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Dev / ACE_Prgs.lha / lang / lisp.lha / LISP.b < prev    next >
Text File  |  1994-12-15  |  9KB  |  493 lines

  1. {*
  2. ** A LISP interpreter written in ACE BASIC.
  3. **
  4. ** Adapted and extended from a Pascal program found in
  5. ** "What Computing is All About" by Jan L.E. van de SnepScheut,
  6. ** p 203-210. 
  7. **
  8. ** ACE version by: David J Benn
  9. ** Date: 12th-15th December 1994
  10. **
  11. ** This minimal dialect of LISP supports the following primitives:
  12. **
  13. ** car, cdr, cons, atom, eq, cond, lambda, define, nil, t
  14. **
  15. ** This is a pure symbolic-processing subset; no numeric data types 
  16. ** are supported.
  17. ** 
  18. ** All lists are considered to be quoted.
  19. **
  20. ** cond only works in conjunction with defined lambda expressions
  21. ** (ie. functions). The same is true for combined applications of 
  22. ** car and cdr.
  23. **
  24. ** Examples of interaction with the interpreter:
  25. ** --------------------------------------------
  26. **
  27. ** > (car (a b c))
  28. ** a
  29. ** > (define (atomlist (lambda (x)
  30. **         (cond ((eq x nil) t)
  31. **               ((atom (car x)) (atomlist (cdr x)))
  32. **           (t nil)))))
  33. ** (atomlist)
  34. ** > (atomlist (a b c d e)
  35. ** t
  36. *}
  37.  
  38. OPTION O-    '..Don't optimise due to a negation optimisation bug in ACE v2.3.
  39.  
  40. {*
  41. ** Constants.
  42. *}
  43. CONST true    = -1&
  44. CONST false    = 0&
  45. CONST default    = -1&
  46. CONST COMPLEMENT= 2&
  47. CONST JAM2    = 1&
  48.  
  49. CONST alfa    = 9
  50. CONST n     = 1000
  51. CONST maxids    = 100
  52.  
  53. CONST nil    = -1
  54. CONST t        = -2
  55. CONST atom    = -3
  56. CONST eq    = -4
  57. CONST kar    = -5
  58. CONST kdr    = -6
  59. CONST kons    = -7
  60. CONST lambda    = -8
  61. CONST cond    = -9
  62. CONST define    = -10
  63.  
  64. {*
  65. ** Variables.
  66. *}
  67. STRING ch SIZE 2
  68. LONGINT nrofids
  69. DIM STRING ids(maxids) SIZE alfa
  70. DIM LONGINT a(n) 
  71. DIM LONGINT d(n) 
  72. DIM LONGINT inuse(n)
  73. LONGINT oldalp, alp, olp, Free
  74. SHORTINT maxcolor
  75. ADDRESS rp
  76. STRING buf
  77.  
  78. {*
  79. ** Library functions.
  80. *}
  81. LIBRARY "graphics.library"
  82. DECLARE FUNCTION SetDrMd(Rp&,MODE) LIBRARY
  83.  
  84. {*
  85. ** Activate event trapping.
  86. *}
  87. ON BREAK GOTO quit
  88. BREAK ON
  89. ON WINDOW GOTO quit
  90. WINDOW ON
  91.  
  92. {*
  93. ** Subprograms.
  94. *}
  95. SUB cursorON
  96. SHARED maxcolor,rp
  97.   SetDrMd(rp,COMPLEMENT)
  98.   COLOR maxcolor 
  99.   PRINT "|";
  100.   COLOR 1
  101.   SetDrMd(rp,JAM2)
  102. END SUB
  103.  
  104. SUB cursorOFF
  105. SHARED maxcolor,rp
  106.   SetDrMd(rp,COMPLEMENT)
  107.   LOCATE CSRLIN,POS-1
  108.   COLOR maxcolor
  109.   PRINT "|"+CHR$(8);
  110.   COLOR 1
  111.   SetDrMd(rp,JAM2)
  112. END SUB
  113.  
  114. SUB STRING nextch
  115. SHARED buf
  116. STRING k$ SIZE 2
  117.   '..Fill buffer?
  118.   IF LEN(buf) = 0 THEN
  119.     REPEAT
  120.       cursorON
  121.       REPEAT
  122.     SLEEP
  123.           k$ = INKEY$
  124.       UNTIL k$ <> ""
  125.       cursorOFF
  126.       '..CR?
  127.       IF ASC(k$) = 13 THEN k$ = CHR$(10)
  128.       '..Destructive backspace?
  129.       IF k$ = CHR$(8) THEN
  130.         IF LEN(buf) > 0 THEN 
  131.       buf = LEFT$(buf,LEN(buf)-1)
  132.       PRINT CHR$(8);
  133.     END IF
  134.       ELSE
  135.     '..Tab?
  136.         IF ASC(k$) = 9 THEN
  137.           buf = buf + SPACE$(10)
  138.       PRINT SPACE$(10);
  139.         ELSE
  140.       '..Other character.
  141.           buf = buf + k$
  142.           PRINT k$;
  143.         END IF
  144.       END IF
  145.     UNTIL ASC(k$) = 10
  146.   END IF
  147.   '..Return left-most character in buffer.
  148.   nextch = LEFT$(buf,1)
  149.   buf = RIGHT$(buf,LEN(buf)-1)
  150. END SUB
  151.  
  152. SUB erm(LONGINT num)
  153. SHARED alp, oldalp, ch
  154.   PRINT
  155.   PRINT "*** error : ";
  156.   CASE
  157.     num=1  : PRINT "illegal application : no function name"
  158.     num=2  : PRINT "car of an atom"
  159.     num=3  : PRINT "cdr of an atom"
  160.     num=4  : PRINT "garbage collector finds no free space"
  161.     num=5  : PRINT "symbol ) expected"
  162.     num=6  : PRINT "incorrect starting symbol of expression [ASCII";STR$(ASC(ch));"]"
  163.     num=7  : PRINT "too many identifiers"
  164.     num=8  : PRINT "undefined identifier"
  165.     num=9  : PRINT "too few actual parameters"
  166.     num=10 : PRINT "too many actual parameters"
  167.   END CASE
  168.   alp = oldalp 
  169.   ch = " "
  170.   GOTO 13
  171. END SUB
  172.  
  173. SUB LONGINT letter(STRING c)
  174.   IF c >= "A" AND c <= "Z" THEN  
  175.     letter = true
  176.   ELSE
  177.     IF c >= "a" AND c <= "z" THEN
  178.       letter = true
  179.     ELSE
  180.       IF c >= "0" AND c <= "9" THEN
  181.     letter = true
  182.       ELSE
  183.     letter = false
  184.       END IF
  185.     END IF
  186.   END IF
  187. END SUB
  188.  
  189. SUB LONGINT identifier
  190. SHARED ch, nrofids, ids
  191. LONGINT i, j
  192. STRING id SIZE alfa
  193.   j=0
  194.   WHILE letter(ch)
  195.     IF j <> alfa-1 THEN 
  196.       ++j
  197.       id = id + ch
  198.     END IF
  199.     ch = nextch
  200.   WEND 
  201.   IF nrofids = maxids THEN CALL erm(7)
  202.   ids(nrofids+1) = id
  203.   i=1
  204.   WHILE ids(i) <> id
  205.     ++i
  206.   WEND
  207.   IF i > nrofids THEN nrofids = i
  208.   identifier =  -i
  209. END SUB
  210.  
  211. SUB printatom(LONGINT x)
  212. SHARED ids
  213.   PRINT ids(-x);
  214. END SUB
  215.  
  216. SUB skipspaces
  217. SHARED ch
  218.   WHILE ASC(ch) = 32 OR ASC(ch) = 9 OR ASC(ch) = 10 OR ch = ";"
  219.     IF ch = ";" THEN
  220.       WHILE ASC(ch) <> 10
  221.     ch = nextch
  222.       WEND
  223.     END IF
  224.     ch = nextch 
  225.   WEND
  226. END SUB
  227.  
  228. SUB LONGINT islist(LONGINT x)
  229. SHARED d
  230.   WHILE x > 0
  231.     x = d(x)
  232.   WEND
  233.   islist = (x = nil)
  234. END SUB
  235.  
  236. SUB printit(LONGINT x)
  237. SHARED a, d 
  238.   IF x < 0 THEN
  239.     printatom(x)
  240.   ELSE
  241.     PRINT "(";
  242.     IF islist(x) THEN
  243.       printit(a(x)) : x = d(x) 
  244.       WHILE x > 0
  245.         PRINT " "; 
  246.        printit(a(x)) : x = d(x)
  247.       WEND 
  248.     ELSE
  249.       printit(a(x)) : PRINT " . "; : printit(d(x))
  250.     END IF
  251.     PRINT ")";
  252.   END IF
  253. END SUB
  254.  
  255. SUB mark(LONGINT ref)
  256. SHARED inuse, a, d
  257.   IF ref <= 0 THEN EXIT SUB 
  258.   WHILE ref > 0 AND NOT inuse(ref)  '..if ref < 0 -> illegal array subscript!!
  259.     inuse(ref) = true 
  260.     mark(a(ref))
  261.     ref = d(ref)
  262.   WEND
  263. END SUB
  264.  
  265. SUB collectgarbage
  266. SHARED inuse, olp, alp, d, Free
  267. LONGINT i
  268.   PRINT "Collecting garbage... ";
  269.   FOR i=1 TO n : inuse(i) = false : NEXT
  270.   mark(olp) : mark(alp)
  271.   FOR i=1 TO n
  272.     IF NOT inuse(i) THEN 
  273.       d(i) = Free
  274.       Free = i
  275.     END IF
  276.   NEXT
  277.   PRINT "done."
  278.   IF Free = nil THEN CALL erm(4)
  279. END SUB
  280.  
  281. SUB LONGINT cons(LONGINT x, LONGINT y)
  282. SHARED Free, d, a
  283. LONGINT ref
  284.   IF Free = nil THEN CALL collectgarbage
  285.   ref = Free : cons = ref : Free = d(ref)
  286.   a(ref) = x : d(ref) = y
  287. END SUB
  288.  
  289. SUB LONGINT car(LONGINT x)
  290. SHARED a
  291.   IF x < 0 THEN CALL erm(2)
  292.   car = a(x)
  293. END SUB
  294.  
  295. SUB LONGINT cdr(LONGINT x)
  296. SHARED d
  297.   IF x < 0 THEN CALL erm(3)
  298.   cdr = d(x)
  299. END SUB
  300.  
  301. SUB LONGINT readitem
  302. SHARED ch, olp, a, d
  303. LONGINT x, tmp, theItem
  304.   skipspaces
  305.   IF letter(ch) THEN
  306.     readitem = identifier
  307.   ELSE
  308.     IF ch <> "(" THEN CALL erm(6)
  309.     ch = nextch
  310.     skipspaces
  311.     IF ch = ")" THEN 
  312.       ch = nextch : readitem = nil
  313.     ELSE
  314.       olp = cons(nil,olp) : x = cons(nil,nil) : a(olp) = x
  315.       theItem = x
  316.       tmp = readitem : a(x) = tmp : skipspaces
  317.       IF ch = "." THEN
  318.            ch = nextch : tmp = readitem : d(x) = tmp
  319.     skipspaces : IF ch <> ")" THEN CALL erm(5)
  320.       ELSE
  321.     WHILE ch <> ")"
  322.       tmp = cons(nil,nil) : d(x) = tmp : x = d(x)
  323.       tmp = readitem : a(x) = tmp : skipspaces
  324.     WEND
  325.       END IF
  326.       ch = nextch : olp = d(olp)
  327.     END IF
  328.     readitem = theItem
  329.   END IF
  330. END SUB
  331.  
  332. DECLARE SUB LONGINT eval(LONGINT e)
  333.  
  334. SUB LONGINT evcon(LONGINT x)
  335. SHARED d, a
  336.   WHILE eval(car(car(x))) = nil 
  337.     x = d(x)
  338.   WEND
  339.   evcon = eval(car(d(a(x))))
  340. END SUB
  341.  
  342. SUB LONGINT evlis(LONGINT x)
  343. SHARED olp, a, d
  344. LONGINT op, retVal, tmp
  345.   IF x = nil THEN
  346.     evlis = nil
  347.   ELSE
  348.     op = olp : olp = cons(nil,olp)
  349.     retVal = olp
  350.     tmp = eval(car(x)) : a(olp) = tmp
  351.     tmp = evlis(d(x)) : d(olp) = tmp
  352.     olp = op 
  353.     evlis = retVal
  354.   END IF
  355. END SUB
  356.  
  357. SUB LONGINT assoc(LONGINT x)
  358. SHARED alp, a, d
  359. LONGINT al
  360.   al = alp
  361.   WHILE al <> nil AND a(a(al)) <> x
  362.     al = d(al)
  363.   WEND
  364.   IF al = nil THEN CALL erm(8)
  365.   assoc = d(a(al)) 
  366. END SUB
  367.  
  368. SUB pairlis(LONGINT x, LONGINT y)
  369. SHARED alp, a
  370. LONGINT tmp
  371.   IF x <> nil THEN
  372.     IF y = nil THEN CALL erm(9)
  373.     pairlis(cdr(x), cdr(y))
  374.     alp = cons(nil,alp) : tmp = cons(a(x),a(y)) : a(alp) = tmp
  375.   ELSE
  376.     IF y <> nil THEN CALL erm(10) 
  377.   END IF 
  378. END SUB
  379.  
  380. SUB LONGINT logical(LONGINT b)
  381.   IF b THEN logical = t ELSE logical = nil
  382. END SUB
  383.  
  384. SUB LONGINT apply(LONGINT func, LONGINT x)
  385. SHARED a, alp, d
  386. LONGINT ap
  387.   IF func < 0 THEN
  388.     CASE 
  389.       func = kar  : apply = car(car(x))
  390.       func = kdr  : apply = cdr(car(x))
  391.       func = kons : apply = cons(car(x),car(cdr(x)))
  392.       func = atom : apply = logical(car(x) < 0)
  393.       func = eq   : apply = logical(car(x) = car(cdr(x)))
  394.       default     : apply = apply(assoc(func),x)
  395.     END CASE
  396.   ELSE
  397.     IF a(func) = lambda THEN
  398.       ap = alp : pairlis(car(d(func)),x)
  399.       apply = eval(car(d(d(func)))) : alp = ap
  400.     ELSE
  401.       erm(1)
  402.     END IF
  403.   END IF
  404. END SUB
  405.  
  406. SUB LONGINT eval(LONGINT e)
  407. SHARED a, d, olp
  408. LONGINT tmp
  409.   IF e < 0 THEN
  410.     IF e = nil OR e = t THEN eval = e ELSE eval = assoc(e)
  411.   ELSE
  412.     IF a(e) = quote THEN
  413.       eval = car(d(e))
  414.     ELSE
  415.       IF a(e) = cond THEN
  416.         eval = evcon(d(e))
  417.       ELSE
  418.     olp = cons(nil,olp) : tmp = evlis(d(e)) : a(olp) = tmp
  419.        eval = apply(a(e),a(olp)) : olp = d(olp)
  420.       END IF
  421.     END IF
  422.   END IF
  423. END SUB
  424.  
  425. SUB interpret
  426. SHARED olp, ch, a, d, alp
  427. LONGINT e, p, tmp
  428.   PRINT "> ";
  429.   skipspaces
  430.   olp = nil : olp = cons(nil,nil)
  431.   e = readitem : a(olp) = e
  432.   IF car(e) = define THEN
  433.     e = d(e) : PRINT "(";
  434.     REPEAT
  435.       p = car(e) : printit(car(p)) : alp = cons(nil,alp)
  436.       tmp = cons(a(p),car(d(p))) : a(alp) = tmp : e = cdr(e)
  437.       IF e <> nil THEN PRINT " ";
  438.     UNTIL e = nil
  439.     PRINT ")"
  440.   ELSE
  441.     printit(apply(a(e),d(e))) : PRINT
  442.   END IF
  443. END SUB
  444.  
  445. {*
  446. ** Main.
  447. *}
  448. WINDOW 1,"LISP Interpreter - version 1.0",(0,0)-(640,200)
  449. rp = WINDOW(8)
  450. maxcolor = WINDOW(6)
  451.  
  452. PRINT "Setting up..."
  453.  
  454. FOR i% = 1 TO n-1 
  455.   d(i%) = i%+1
  456. NEXT
  457.  
  458. d(n) = nil
  459. Free = 1
  460.  
  461. ids(-nil)     = "nil"
  462. ids(-t)     = "t"
  463. ids(-atom)     = "atom"
  464. ids(-eq)    = "eq"
  465. ids(-kar)    = "car"
  466. ids(-kdr)    = "cdr"
  467. ids(-kons)    = "cons"
  468. ids(-lambda)    = "lambda"
  469. ids(-cond)    = "cond"
  470. ids(-define)    = "define"
  471.     
  472. nrofids = 10
  473. alp = nil
  474. ch = " "
  475.  
  476. CLS
  477.  
  478. 13 REPEAT
  479.      oldalp = alp
  480.      interpret
  481.    UNTIL false
  482.  
  483. {*
  484. ** Event handler.
  485. *}
  486. quit:
  487.   cursorOFF
  488.   PRINT
  489.   PRINT "*** Break: LISP terminating." 
  490.   SLEEP FOR .75 
  491.   WINDOW CLOSE 1
  492. STOP
  493.